﻿using Green.AgileMapper.MappingRule;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Green.AgileMapper;
using System.Data;
using Green.Utility;

namespace Green.AgileMapper.Test
{
    /// <summary>
    /// AutoMapperTest 的摘要说明
    /// </summary>
    [TestClass]
    public class AutoMapperTest
    {
        public AutoMapperTest()
        {
            KnowTypeMappingPool.Current.Add(typeof(Test1),typeof(Test1));
            KnowTypeMappingPool.Current.Add(typeof(Test2),typeof(Test2));

        }

        private TestContext testContextInstance;

        /// <summary>
        ///获取或设置测试上下文，该上下文提供
        ///有关当前测试运行及其功能的信息。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 附加测试属性
        //
        // 编写测试时，还可使用以下附加属性:
        //
        // 在运行类中的第一个测试之前使用 ClassInitialize 运行代码
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // 在类中的所有测试都已运行之后使用 ClassCleanup 运行代码
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // 在运行每个测试之前，使用 TestInitialize 来运行代码
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // 在每个测试运行完之后，使用 TestCleanup 来运行代码
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void AttributeConfig_SimpleMapping_Gen()
        {

            StudenDo stu = new StudenDo()
            {
                ID = 1,
                Name = "test1",
                Sex = Sex.女,
                Address = new Address()
                {
                    Country = "中国",
                    Province = "四川",
                    Street = "高新区"
                },
                CourseIds = new List<string>() { "1", "2", "3" },
                Propertys = new List<KeyValuePair>() { new KeyValuePair() { Key = "1", Value = "1" } },
                ContactWay = new ContactWay()
                {
                    Phone = "1111111111111111",
                    Email = "xxxx@12f",
                    QQ = "7889789999889"
                },
                Test = new Test2(){Id=1,Property2 = "prperty2"},
                Tests = new List<TestBase>(){new Test1(){Id=1,Property1 = "1"},new Test2(){Id=2,Property2="2"}}
            };

            var mapper = ObjectMapperManager.Default.GetMapper<StudenDto, StudenDo>();

            var dt1 = DateTime.Now;
            var stuDto = mapper.Warp(stu);
            var sp = DateTime.Now - dt1;

            dt1 = DateTime.Now;
            stuDto = mapper.Warp(stu);
            var sp1 = DateTime.Now - dt1;

            Assert.AreEqual(stuDto.ID, stu.ID);
            Assert.AreEqual(stuDto.Name, stu.Name);
            Assert.AreEqual(stuDto.Sex, stu.Sex);
            Assert.AreEqual(stuDto.Country, stu.Address.Country);
            Assert.AreEqual(stuDto.Province, stu.Address.Province);
            Assert.AreEqual(stuDto.Street, null);//Ignore
            //object
            // Assert.AreEqual(stuDto.ContactWay,null);
            Assert.AreEqual(stuDto.ContactWay.QQ, stu.ContactWay.QQ);
            Assert.AreEqual(stuDto.ContactWay.Email, stu.ContactWay.Email);
            //expression
            Assert.AreEqual(stuDto.Particular, string.Format("{0} 国籍 {1} 省 ", stu.Address.Country, stu.Address.Province));
            Assert.AreEqual(stuDto.FirstPropertyKey, stu.Propertys[0].Key);
            //collection            
            Assert.AreEqual(stuDto.CourseIds[0], stu.CourseIds[0]);
            Assert.AreEqual(stuDto.CourseIds.Count, stu.CourseIds.Count);

            Assert.AreEqual(stuDto.Propertys[0].Key, stu.Propertys[0].Key);
            Assert.AreEqual(stuDto.Propertys[0].Value, stu.Propertys[0].Value);
            Assert.AreEqual(stuDto.Propertys.Count, stu.Propertys.Count);

            //Warp 2
            var stuDo = new StudenDo();
            mapper.Warp(stuDto, stuDo);

            Assert.AreEqual(stuDo.ID, stuDto.ID);
            Assert.AreEqual(stuDo.Name, stuDto.Name);
            Assert.AreEqual(stuDo.Sex, stuDto.Sex);
            Assert.AreEqual(stuDo.Address.Country, stuDto.Country);
            Assert.AreEqual(stuDo.Address.Province, stuDto.Province);
            //Assert.AreEqual(stuDo.Address.Street, null);//Ignore
            //object
            Assert.AreEqual(stuDo.ContactWay.QQ, stuDto.ContactWay.QQ);
            Assert.AreEqual(stuDo.ContactWay.Email, stuDto.ContactWay.Email);
            //collection

            Assert.AreEqual(stuDo.CourseIds.Count, stuDto.CourseIds.Count);
            Assert.AreEqual(stuDo.CourseIds[0], stuDto.CourseIds[0]);

            Assert.AreEqual(stuDo.Propertys.Count, stuDto.Propertys.Count);
            Assert.AreEqual(stuDo.Propertys[0].Key, stuDto.Propertys[0].Key);
            Assert.AreEqual(stuDo.Propertys[0].Value, stuDto.Propertys[0].Value);
        }

        [TestMethod]
        public void AttributeConfig_SimpleMapping()
        {
            StudenDo stu = new StudenDo()
            {
                ID = 1,
                Name = "test1",
                Sex = Sex.女,
                Address = new Address()
                {
                    Country = "中国",
                    Province = "四川",
                    Street = "高新区"
                },
                CourseIds = new List<string>() { "1", "2", "3" },
                Propertys = new List<KeyValuePair>() { new KeyValuePair() { Key = "1", Value = "1" } },
                ContactWay = new ContactWay()
                {
                    Phone = "1111111111111111",
                    Email = "xxxx@12f",
                    QQ = "7889789999889"
                }
            };

            var mapper = ObjectMapperManager.Default.GetMapper();
            var stuDto = mapper.Warp(typeof(StudenDto), stu) as StudenDto;

            Assert.AreEqual(stuDto.ID, stu.ID);
            Assert.AreEqual(stuDto.Name, stu.Name);
            Assert.AreEqual(stuDto.Sex, stu.Sex);
            Assert.AreEqual(stuDto.Country, stu.Address.Country);
            Assert.AreEqual(stuDto.Province, stu.Address.Province);
            Assert.AreEqual(stuDto.Street, null);//Ignore
            //object
            Assert.AreEqual(stuDto.ContactWay.QQ, stu.ContactWay.QQ);
            Assert.AreEqual(stuDto.ContactWay.Email, stu.ContactWay.Email);
            //expression
            Assert.AreEqual(stuDto.Particular, string.Format("{0} 国籍 {1} 省 ", stu.Address.Country, stu.Address.Province));
            //collection            
            Assert.AreEqual(stuDto.CourseIds[0], stu.CourseIds[0]);
            Assert.AreEqual(stuDto.CourseIds.Count, stu.CourseIds.Count);
        }

        [TestMethod]
        public void XMlConfig_SimpleMapping_Gen()
        {

            StudenDo stu = new StudenDo()
            {
                ID = 1,
                Name = "test1",
                Sex = Sex.女,
                Address = new Address()
                {
                    Country = "中国",
                    Province = "四川",
                    Street = "高新区"
                },
                CourseIds = new List<string>() { "1", "2", "3" },
                Propertys = new List<KeyValuePair>() { new KeyValuePair() { Key = "1", Value = "1" } },
                ContactWay = new ContactWay()
                {
                    Phone = "1111111111111111",
                    Email = "xxxx@12f",
                    QQ = "7889789999889"
                }
            };

            var mapper = ObjectMapperManager.Default.GetMapper<StudenDto, StudenDo>(new XMLMappingConfigurator(@"E:\Project\OpenSource\AgileMapper\AgileMappper.Test\XMLConfigurator\AgileMapper.xml"));


            var stuDto = mapper.Warp(stu);

            Assert.AreEqual(stuDto.ID, stu.ID);
            Assert.AreEqual(stuDto.Name, stu.Name);
            Assert.AreEqual(stuDto.Sex, stu.Sex);
            Assert.AreEqual(stuDto.Country, stu.Address.Country);
            Assert.AreEqual(stuDto.Province, stu.Address.Province);
            Assert.AreEqual(stuDto.Street, null);//Ignore
            //object
            // Assert.AreEqual(stuDto.ContactWay,null);
            Assert.AreEqual(stuDto.ContactWay.QQ, stu.ContactWay.QQ);
            Assert.AreEqual(stuDto.ContactWay.Email, stu.ContactWay.Email);
            //expression
            Assert.AreEqual(stuDto.Particular.Replace(" ", ""), string.Format("{0}{1}", stu.Address.Country, stu.Address.Province));
            Assert.AreEqual(stuDto.FirstPropertyKey, stu.Propertys[0].Key);
            //collection            
            Assert.AreEqual(stuDto.CourseIds[0], stu.CourseIds[0]);
            Assert.AreEqual(stuDto.CourseIds.Count, stu.CourseIds.Count);

            Assert.AreEqual(stuDto.Propertys[0].Key, stu.Propertys[0].Key);
            Assert.AreEqual(stuDto.Propertys[0].Value, stu.Propertys[0].Value);
            Assert.AreEqual(stuDto.Propertys.Count, stu.Propertys.Count);

            //Warp 2
            var stuDo = new StudenDo();
            mapper.Warp(stuDto, stuDo);

            Assert.AreEqual(stuDo.ID, stuDto.ID);
            Assert.AreEqual(stuDo.Name, stuDto.Name);
            Assert.AreEqual(stuDo.Sex, stuDto.Sex);
            Assert.AreEqual(stuDo.Address.Country, stuDto.Country);
            Assert.AreEqual(stuDo.Address.Province, stuDto.Province);
            //Assert.AreEqual(stuDo.Address.Street, null);//Ignore
            //object
            Assert.AreEqual(stuDo.ContactWay.QQ, stuDto.ContactWay.QQ);
            Assert.AreEqual(stuDo.ContactWay.Email, stuDto.ContactWay.Email);
            //collection

            Assert.AreEqual(stuDo.CourseIds.Count, stuDto.CourseIds.Count);
            Assert.AreEqual(stuDo.CourseIds[0], stuDto.CourseIds[0]);

            Assert.AreEqual(stuDo.Propertys.Count, stuDto.Propertys.Count);
            Assert.AreEqual(stuDo.Propertys[0].Key, stuDto.Propertys[0].Key);
            Assert.AreEqual(stuDo.Propertys[0].Value, stuDto.Propertys[0].Value);
        }


        [TestMethod]
        public void DataRowConfig_SameTable_DataRowCloneMapping()
        {
            DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[] { 
                new DataColumn("ID",typeof(int)),
                new DataColumn("Name",typeof(string))
            });

            var row = dt.NewRow();
            row[0] = 1;
            row[1] = "Green";
            dt.Rows.Add(row);

            var rowClone = dt.NewRow();

            var mapper = ObjectMapperManager.Default.GetMapper(new DataRowMappingConfigurator());
            mapper.Warp(typeof(DataRow), row, rowClone);
            Assert.AreEqual(row[0], rowClone[0]);
            Assert.AreEqual(row[1], rowClone[1]);
        }

        [TestMethod]
        public void DataRowConfig_UnSameTable_MutipleRule_DataRowCloneMapping()
        {
            DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[] { 
                new DataColumn("ID",typeof(int)),
                new DataColumn("Name",typeof(string))
            });

            DataTable dt2 = new DataTable();
            dt2.Columns.AddRange(new DataColumn[] { 
                new DataColumn("ID",typeof(int)),
                new DataColumn("Name",typeof(string)),
                 new DataColumn("Sex",typeof(string))
            });


            var row = dt2.NewRow();
            row[0] = 1;
            row[1] = "Green";
            row[2] = "Nan";
            dt2.Rows.Add(row);

            var rowClone = dt.NewRow();

            var mapper = ObjectMapperManager.Default.GetMapper(new DataRowMappingConfigurator());
            mapper.Warp(row, rowClone);
            Assert.AreEqual(row[0], rowClone[0]);
            Assert.AreEqual(row[1], rowClone[1]);
        }


        [TestMethod]
        public void DataRowConfig_UnSameTable_Not_MutipleRule_DataRowCloneMapping()
        {
            DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[] { 
                new DataColumn("ID",typeof(int)),
                new DataColumn("Name",typeof(string))
            });

            DataTable dt2 = new DataTable();
            dt2.Columns.AddRange(new DataColumn[] { 
                new DataColumn("ID",typeof(int)),
                new DataColumn("Name",typeof(string)),
                 new DataColumn("Sex",typeof(string))
            });


            var row = dt.NewRow();
            row[0] = 1;
            row[1] = "Green";
            dt.Rows.Add(row);

            var rowClone = dt2.NewRow();

            var mapper = ObjectMapperManager.Default.GetMapper(new DataRowMappingConfigurator());
            mapper.Warp(row, rowClone);
            Assert.AreEqual(row[0], rowClone[0]);
            Assert.AreEqual(row[1], rowClone[1]);
        }

        [TestMethod]
        public void DataRowConfig_To_Object_CloneMapping()
        {
            DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[] { 
                new DataColumn("ID",typeof(int)),
                new DataColumn("Name",typeof(string))
            });

            var row = dt.NewRow();
            row[0] = 1;
            row[1] = "Green";
            dt.Rows.Add(row);
            StudentModelForDataRow model = new StudentModelForDataRow();

            var mapper = ObjectMapperManager.Default.GetMapper(new DataRowMappingConfigurator());
            mapper.Warp(row, model);
            Assert.AreEqual(model.ID, row[0]);
            Assert.AreEqual(model.Name, row[1]);
        }


        [TestMethod]
        public void GeneratorTest()
        {

            StudenDo stu = new StudenDo()
            {
                ID = 1,
                Name = "test1",
                Sex = Sex.女,
                Address = new Address()
                {
                    Country = "中国",
                    Province = "四川",
                    Street = "高新区"
                },
                CourseIds = new List<string>() { "1", "2", "3" },
                Propertys = new List<KeyValuePair>() { new KeyValuePair() { Key = "1", Value = "1" } },
                ContactWay = new ContactWay()
                {
                    Phone = "1111111111111111",
                    Email = "xxxx@12f",
                    QQ = "7889789999889"
                }
            };
            Func<StudenDo, StudenDo, bool> fun = (f, j) => f.ID == j.ID;
            var s = fun.ToString();

            var mapper = ObjectMapperManager.Default.GetMapper<StudenDto, StudenDo>();
            mapper.AgileMapperTemplateStrategy.DefaultEqualExpression = "{0}.ID == {1}.ID && {1}.ID != 0";
            var str1 = mapper.CodeGenerator();
            System.IO.File.Delete(@"E:\Project\OpenSource\AgileMapper\AgileMappper.Test\CodeTemplate.Test\1.cs");
            System.IO.File.AppendAllText(@"E:\Project\OpenSource\AgileMapper\AgileMappper.Test\CodeTemplate.Test\1.cs", str1 );

            var mapper1 = ObjectMapperManager.Default.GetMapper<ContactWayDto, ContactWay>();
            str1 = mapper1.CodeGenerator();
            System.IO.File.Delete(@"E:\Project\OpenSource\AgileMapper\AgileMappper.Test\CodeTemplate.Test\2.cs");
            System.IO.File.AppendAllText(@"E:\Project\OpenSource\AgileMapper\AgileMappper.Test\CodeTemplate.Test\2.cs", str1 );

            var mapper2 = ObjectMapperManager.Default.GetMapper<KeyValuePairDto, KeyValuePair>();
            str1 = mapper2.CodeGenerator();
            System.IO.File.Delete(@"E:\Project\OpenSource\AgileMapper\AgileMappper.Test\CodeTemplate.Test\3.cs");
            System.IO.File.AppendAllText(@"E:\Project\OpenSource\AgileMapper\AgileMappper.Test\CodeTemplate.Test\3.cs", str1 );


        }

    }
}
